package com.ou.csbs.capstone.driver;


import gov.nasa.worldwind.Configuration;
import gov.nasa.worldwind.render.Material;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;

import javax.swing.JFrame;
import javax.swing.plaf.basic.BasicBorders;

import com.ou.csbs.capstone.controllers.menu.MenuBarController;
import com.ou.csbs.capstone.controllers.menu.ToolBarController;
import com.ou.csbs.capstone.models.AttributeModel;
import com.ou.csbs.capstone.models.RenderableModel;
import com.ou.csbs.capstone.tools.StatusBarTool;
import com.ou.csbs.capstone.views.menu.MenuBar;
import com.ou.csbs.capstone.views.menu.StatusBar;
import com.ou.csbs.capstone.views.menu.ToolBar;
import com.ou.csbs.capstone.views.worldwind.WorldWindCanvas;

/**
 * Main driver for the Capstone project. It instantiates all required WorldWind objects, as well as the Capstone additions.
 * @author Senior Capstone
 */
public class Driver {
	/**
	 * Main method
	 */
	public static void main(String[] args) {
		extractLibraries();

		Configuration.setValue("gov.nasa.worldwind.avkey.InitialLatitude", 39);
		Configuration.setValue("gov.nasa.worldwind.avkey.InitialLongitude", -98); //middle of the United States
		//build Java swing interface
		WorldWindCanvas.initialize();
		JFrame frame = new JFrame("World Wind");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLayout(new BorderLayout());
		frame.add(WorldWindCanvas.getWorldWindow(), BorderLayout.CENTER);

		//set default AttributeModel Settings for shapes in the Drawing layer
		AttributeModel.setFill(false);
		AttributeModel.setOutlineColor(Material.WHITE);
		AttributeModel.setLineWidth(2);
		AttributeModel.setLineStipple(AttributeModel.STIPPLE_PATTERN_0);

		//create Capstone additions
		RenderableModel model = new RenderableModel();
		MenuBar menuBar = new MenuBar();
		menuBar.setBorder(BasicBorders.getMenuBarBorder());
		MenuBarController mbctrl = new MenuBarController();
		mbctrl.setMenuBar(menuBar);
		ToolBar toolbar = new ToolBar();
		ToolBarController tbctrl = new ToolBarController(model);
		tbctrl.setToolBar(toolbar);
		StatusBar status = new StatusBar();
		WorldWindCanvas.addMouseMotionListener(new StatusBarTool());

		//add Capstone additions to JFrame
		frame.add(toolbar, BorderLayout.NORTH);
		frame.add(status, BorderLayout.SOUTH);
		frame.setExtendedState(Frame.MAXIMIZED_BOTH);
		frame.setJMenuBar(menuBar);
		frame.setVisible(true);	
	}

	/**
	 * Handles the identification of the host system and extracts the required WorldWind libraries from its resource path
	 */
	public static void extractLibraries(){
		try {
			String osType = System.getProperty("os.name");
			String arch = System.getProperty("os.arch");
			File projectRoot = new File(".");
			File[] projectRootContents = projectRoot.listFiles();
			//if these files have been extracted before, skip
			for(File x: projectRootContents){
				String name = x.getName();
				if(name.contains("dll") || name.contains("so") || name.contains("jnilib"))
					return;
			}
			if(osType.startsWith("Windows")){
				if(arch.contains("64")){
					InputStream gluegen = Driver.class.getResourceAsStream("Win64/gluegen-rt.dll");
					InputStream jogl_desktop = Driver.class.getResourceAsStream("Win64/jogl_desktop.dll");
					InputStream jogl_mobile = Driver.class.getResourceAsStream("Win64/jogl_mobile.dll");
					InputStream nwawt = Driver.class.getResourceAsStream("Win64/nativewindow_awt.dll");
					InputStream nwwin32 = Driver.class.getResourceAsStream("Win64/nativewindow_win32.dll");
					InputStream newt = Driver.class.getResourceAsStream("Win64/newt.dll");
					extractResource(gluegen, "gluegen-rt.dll");
					extractResource(jogl_desktop, "jogl_desktop.dll");
					extractResource(jogl_mobile, "jogl_mobile.dll");
					extractResource(nwawt, "nativewindow_awt.dll");
					extractResource(nwwin32, "nativewindow_win32.dll");
					extractResource(newt, "newt.dll");

				}
				else{
					InputStream gluegen = Driver.class.getResourceAsStream("Win32/gluegen-rt.dll");
					InputStream jogl_desktop = Driver.class.getResourceAsStream("Win32/jogl_desktop.dll");
					InputStream jogl_mobile = Driver.class.getResourceAsStream("Win32/jogl_mobile.dll");
					InputStream nwawt = Driver.class.getResourceAsStream("Win32/nativewindow_awt.dll");
					InputStream nwwin32 = Driver.class.getResourceAsStream("Win32/nativewindow_win32.dll");
					InputStream newt = Driver.class.getResourceAsStream("Win32/newt.dll");
					extractResource(gluegen, "gluegen-rt.dll");
					extractResource(jogl_desktop, "jogl_desktop.dll");
					extractResource(jogl_mobile, "jogl_mobile.dll");
					extractResource(nwawt, "nativewindow_awt.dll");
					extractResource(nwwin32, "nativewindow_win32.dll");
					extractResource(newt, "newt.dll");
				}
			}
			else if(osType.startsWith("Mac")){
				InputStream gluegen = Driver.class.getResourceAsStream("MacOSX/libgluegen-rt.jnilib");
				InputStream jogl_desktop = Driver.class.getResourceAsStream("MacOSX/libjogl_desktop.jnilib");
				InputStream jogl_mobile = Driver.class.getResourceAsStream("MacOSX/libjogl_mobile.jnilib");
				InputStream nwawt = Driver.class.getResourceAsStream("MacOSX/libnativewindow_awt.jnilib");
				InputStream nwmacosx = Driver.class.getResourceAsStream("MacOSX/libnativewindow_macosx.jnilib");
				InputStream newt = Driver.class.getResourceAsStream("MacOSX/libnewt.jnilib");
				extractResource(gluegen, "libgluegen-rt.jnilib");
				extractResource(jogl_desktop, "libjogl_desktop.jnilib");
				extractResource(jogl_mobile, "libjogl_mobile.jnilib");
				extractResource(nwawt, "libnativewindow_awt.jnilib");
				extractResource(nwmacosx, "libnativewindow_macosx.jnilib");
				extractResource(newt, "libnewt.jnilib");
			}
			else{
				if(arch.contains("64")){
					InputStream gluegen = Driver.class.getResourceAsStream("Lin64/libgluegen-rt.so");
					InputStream jogl_desktop = Driver.class.getResourceAsStream("Lin64/libjogl_desktop.so");
					InputStream jogl_mobile = Driver.class.getResourceAsStream("Lin64/libjogl_mobile.so");
					InputStream nwawt = Driver.class.getResourceAsStream("Lin64/libnativewindow_awt.so");
					InputStream nwlinux = Driver.class.getResourceAsStream("Lin64/libnativewindow_x11.so");
					InputStream newt = Driver.class.getResourceAsStream("Lin64/libnewt.so");
					extractResource(gluegen, "libgluegen-rt.so");
					extractResource(jogl_desktop, "libjogl_desktop.so");
					extractResource(jogl_mobile, "libjogl_mobile.so");
					extractResource(nwawt, "libnativewindow_awt.so");
					extractResource(nwlinux, "libnativewindow_x11.so");
					extractResource(newt, "libnewt.so");
				}
				else{
					InputStream gluegen = Driver.class.getResourceAsStream("Lin32/libgluegen-rt.so");
					InputStream jogl_desktop = Driver.class.getResourceAsStream("Lin32/libjogl_desktop.so");
					InputStream jogl_mobile = Driver.class.getResourceAsStream("Lin32/libjogl_mobile.so");
					InputStream nwawt = Driver.class.getResourceAsStream("Lin32/libnativewindow_awt.so");
					InputStream nwlinux = Driver.class.getResourceAsStream("Lin32/libnativewindow_x11.so");
					InputStream newt = Driver.class.getResourceAsStream("Lin32/libnewt.so");
					extractResource(gluegen, "libgluegen-rt.so");
					extractResource(jogl_desktop, "libjogl_desktop.so");
					extractResource(jogl_mobile, "libjogl_mobile.so");
					extractResource(nwawt, "libnativewindow_awt.so");
					extractResource(nwlinux, "libnativewindow_x11.so");
					extractResource(newt, "libnewt.so");
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * Copies an internal resource (from say, a jar file) to the jar's base directory
	 * @param in The InputStream for the resource
	 * @param name The name to give the copied resource
	 * @throws IOException If the copy operation fails for whatever reason
	 */
	private static void extractResource(InputStream in, String name) throws IOException{
		File out = new File(".\\"+name);
		Files.copy(in, out.toPath());
	}
}
